/*
 *  GEPoint3d.h
 *  GameEngine
 *
 *  Created by Quoc Dung Chu on 14/07/11.
 *  Copyright 2011 Paris 6. All rights reserved.
 *
 */

#ifndef GE_TUPLE_3D_H
#define GE_TUPLE_3D_H

#include "GEMath.h"

namespace game_engine
{
	namespace vect_math
	{
		
		template <class T>
		class GETuple3d
		{
		private:
			
			
		public :
			T		X;
			T		Y;
			T		Z;
			//******************************************************************************************
#pragma mark -
#pragma mark CONSTRUCTOR

			GETuple3d () : X(0), Y(0), Z(0) { }
			//----------------------------------------------------------

			GETuple3d (T x, T y, T z) 
			{ 
				X = x;
				Y = y;
				Z = z;
			}
			//******************************************************************************************
			//METHODS
			//UNARY OPERATION
#pragma mark -
#pragma mark UNARY OPERATION
			GETuple3d<T> operator-() { return GETuple3d<T>(-X, -Y, -Z);}
			//----------------------------------------------------------
			GETuple3d<T>& operator=(const GETuple3d<T>& other)
			{
				X = other.X;
				Y = other.Y;
				Z = other.Z;
				return *this;
			}
			//----------------------------------------------------------
			//ARITHMETIC OPERATION 
			
#pragma mark -
#pragma mark ARITHMETIC OPERATION 
			//operator +
			GETuple3d<T> operator+ (const GETuple3d<T>& other) 
			{ 
				return GETuple3d<T>(X + other.X, Y + other.Y, Z + other.Z);
			}
			//----------------------------------------------------------
			GETuple3d<T>& operator+=(const GETuple3d<T>& other)
			{
				X+=other.X();
				Y+=other.Y();
				Z+=other.Z();
				return *this;
			}
			//----------------------------------------------------------
			GETuple3d<T> operator+ (const T val) 
			{ 
				return GETuple3d<T>(X + val, Y + val, Z + val);
			}
			//----------------------------------------------------------
			GETuple3d<T>& operator+=(const T val)
			{
				X+=val;
				Y+=val;
				Z+=val;
				return *this;
			}
			//----------------------------------------------------------
			//operator -
			
			GETuple3d<T> operator- (const GETuple3d<T>& other) 
			{ 
				return GETuple3d<T>(X - other.X, Y - other.Y, Z - other.Z);
			}
			//----------------------------------------------------------

			GETuple3d<T>& operator-=(const GETuple3d<T>& other)
			{
				X-=other.X;
				Y-=other.Y;
				Z-=other.Z;
				return *this;
			}
			//----------------------------------------------------------

			GETuple3d<T> operator- (T val) 
			{ 
				return GETuple3d<T>(X - val, Y - val, Z - val);
			}
			//----------------------------------------------------------

			GETuple3d<T>& operator-=( T val)
			{
				X-=val;
				Y-=val;
				Z-=val;
				return *this;
			}
			//----------------------------------------------------------
			//operator *
			GETuple3d<T> operator* (const GETuple3d<T>& other) 
			{ 
				return GETuple3d<T>(X * other.X(), Y * other.Y(), Z * other.Z());
			}
			
			GETuple3d<T>& operator*=(const GETuple3d<T>& other)
			{
				X*=other.X();
				Y*=other.Y();
				Z*=other.Z();
				return *this;
			}
			//----------------------------------------------------------

			GETuple3d<T> operator* (T val) 
			{ 
				return GETuple3d<T>(X * val, Y * val, Z * val);
			}
			//----------------------------------------------------------

			GETuple3d<T>& operator*=( T val)
			{
				X*=val;
				Y*=val;
				Z*=val;
				return *this;
			}
			//----------------------------------------------------------
			//operator /
			GETuple3d<T> operator/ (const GETuple3d<T>& other) 
			{ 
				return GETuple3d<T>(X / other.X(), Y / other.Y(), Z / other.Z());
			}
			
			GETuple3d<T>& operator/=(const GETuple3d<T>& other)
			{
				X/=other.X();
				Y/=other.Y();
				Z/=other.Z();
				return *this;
			}
			//----------------------------------------------------------
			
			GETuple3d<T> operator/ (T val) 
			{ 
				return GETuple3d<T>(X / val, Y / val, Z / val);
			}
			//----------------------------------------------------------
			
			GETuple3d<T>& operator/=( T val)
			{
				X/=val;
				Y/=val;
				Z/=val;
				return *this;
			}
			
			//----------------------------------------------------------
			//METHODS COMPARING
#pragma mark -
#pragma mark METHODS COMPARING
			
			bool operator==(const GETuple3d<T>& other )
			{
				return this->equal(other);
			}
			//----------------------------------------------------------

			bool operator!=(const GETuple3d<T>& other )
			{
				return !this->equal(other);
			}
			
			//----------------------------------------------------------

			bool equal(const GETuple3d<T>& other)
			{
				return  game_engine::vect_math::equal(X,other.X)
						&& game_engine::vect_math::equal(Y,other.Y)
						&& game_engine::vect_math::equal(Z,other.Z);
			}
			
			//----------------------------------------------------------
			//<= 

			//******************************************************************************************
			//PROPERTIES
			
			GETuple3d<T>& set(T x, T y, T z) 
			{
				X = x;
				Y = y;
				Z = z;
				return *this;
			}
			
		protected:
			//GETuple3d<T> negative () { return GETuple3d<T>(-X, -Y, -Z);}
			
			//T X () { return X; }
//			//----------------------------------------------------------
//			void X (T x) { X = x; }
//			//----------------------------------------------------------
//			T Y () { return Y; }
//			//----------------------------------------------------------
//			void Y (T y) { Y = y; }
//			//----------------------------------------------------------
//			T Z () { return Z; }
//			//----------------------------------------------------------
//			void Z (T z) { Z = z; } 
		};
	}
}
#endif